package com.wxb.plugin.core.gen;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.wxb.plugin.action.Config;
import com.wxb.plugin.core.RepeatCheck;
import com.wxb.plugin.core.parser.TextParser;
import com.wxb.plugin.core.parser.URLParser;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.wxb.plugin.core.gen.QualifyClassName.*;

/**
 * <p>
 *
 * </p>
 *
 * @author weixianbing
 * @create 2022/3/1 17:15
 */
public class InterfaceApiGen2 {
    // 扫描文件夹
//    static String scan = "src/main/java/com/xiaoshuotech/glp/risk/api/controller";
    // 新文档地址
    static String out = "D:\\data\\";
    // 新文档名称前缀
    public static String docxPrefix = "swagger-api-";
    // 子目录标题
    public static String[] subHeader = {"业务描述", "接口提供方", "接口地址",
            "接口请求字段", "接口响应字段", "请求示例报文", "响应示例报文"};

    private static Pattern p = Pattern.compile("(?<=\").*(?=\")");

    //排除字段
    static Set<String> excludeFields = new HashSet<>();
    //排除类
    static Set<String> excludeClass = new HashSet<>();


    static {
//        excludeFields.addAll(Arrays.asList("signature", "version"));
//        excludeClass.addAll(Arrays.asList());
    }

    public static String genFile(Set<PsiClass> psiClassList, Config config) {
        // 文档名称前缀
        if (StringUtil.isNotBlank(config.getFilePre())) {
            docxPrefix = config.getFilePre();
        }
        List<ControllerApiInfo> controllers = new ArrayList<>();
        // 遍历寻找controller，并解析
        for (PsiClass aClass : psiClassList) {
            // 非controller跳过
            if (!isController(aClass)) {
                System.out.println("not controller:" + aClass.getName());
                continue;
            }
            ControllerApiInfo aInfo = new ControllerApiInfo(aClass);
            controllers.add(aInfo);
            System.out.println(aInfo.prefixPath);
            // 解析controller方法
            for (PsiMethod method : aClass.getMethods()) {

                List<String> mapping = URLParser.getMethodUrl(method, aInfo.prefixPath);
                if (mapping.isEmpty()) {
                    continue;
                }
                MethodApiInfo info = getInfo(method);
                info.url = mapping;
                aInfo.methodApiInfos.add(info);
            }
        }
        out = config.getPath();
        System.out.println("开始生成doc---------------------------");
        return config.getFileType().equals("word") ? GenWord.toFile(controllers) : GenMarkDown.toFile(controllers, config);
    }


    public static boolean isController(PsiClass aClass) {
        PsiAnnotation[] annotations = aClass.getAnnotations();
        if (annotations != null) {
            for (PsiAnnotation annotation : annotations) {
                if (restController.equals(annotation.getQualifiedName())
                        || controller.equals(annotation.getQualifiedName())) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 解析方法参数类型，返回参数类型
     */
    public static MethodApiInfo getInfo(PsiMethod method) {

        MethodApiInfo methodApiInfo = new MethodApiInfo();
        methodApiInfo.businessDesc = TextParser.getMethodNote(method);
        methodApiInfo.title = methodApiInfo.businessDesc;
        methodApiInfo.hide = URLParser.hide(method.getAnnotation(Hidden));
        methodApiInfo.paramEntities = new ArrayList<>();
        JSONObject req = new JSONObject();
        // 解析方法参数
        for (PsiParameter parameterType : method.getParameterList().getParameters()) {
            String name = parameterType.getName();
            if (parameterType.getType() instanceof PsiClassReferenceType type) {
                MethodApiInfo.FieldInfo fieldInfo;
                // RequestBody 解析
                if (parameterType.getAnnotation(RequestBody) != null) {

                    JSONObject object = new JSONObject();
                    req.put(name, object);

                    fieldInfo = getEntityInfo(type, methodApiInfo.paramEntities, object, null);
                    fieldInfo.requestType = "Body";
                }
                // PathVariable 解析
                else if (parameterType.getAnnotation(PathVariable) != null) {
                    methodApiInfo.paramEntities.add(getParameterInfo(parameterType.getType(),
                            parameterType.getAnnotation(PathVariable), name, req, null));
                }
                // RequestParam 解析
                else if (parameterType.getAnnotation(RequestParam) != null) {
                    methodApiInfo.paramEntities.add(getParameterInfo(parameterType.getType(),
                            parameterType.getAnnotation(RequestParam), name, req, null));
                }
                // RequestHeader 解析
                else if (parameterType.getAnnotation(RequestHeader) != null) {
                    methodApiInfo.paramEntities.add(getParameterInfo(parameterType.getType(),
                            parameterType.getAnnotation(RequestHeader), name, req, null));
                }
            }
        }
        // 解析返回类型
        JSONObject res = new JSONObject();
        methodApiInfo.returnEntities = getReturnInfo(method, res);

        //设置样例
        methodApiInfo.requestExample = formatContent(req);
        methodApiInfo.responseExample = formatContent(res);
        return methodApiInfo;
    }


    public static List<MethodApiInfo.FieldInfo> getReturnInfo(PsiMethod method, JSONObject res) {
        List<MethodApiInfo.FieldInfo> returnEntities = new ArrayList<>();
        List<Class<?>> sub = new ArrayList<>();
        PsiType returnType = method.getReturnType();
        if (returnType instanceof PsiClassReferenceType) {
            PsiClassReferenceType type = (PsiClassReferenceType) returnType;
            PsiClass resolve = type.resolve();
            if (resolve == null) {
                return null;
            }
        }

        getEntityInfo(returnType, returnEntities, res, null);

        return returnEntities;
    }

    public static String formatContent(Object o) {
        return JSON.toJSONString(o,
                SerializerFeature.PrettyFormat,
                SerializerFeature.WriteNullBooleanAsFalse,
                SerializerFeature.WriteBigDecimalAsPlain,
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteNullListAsEmpty,
                SerializerFeature.WriteNullStringAsEmpty,
                SerializerFeature.WriteNullNumberAsZero,
                SerializerFeature.WriteDateUseDateFormat
        );
    }

    public static MethodApiInfo.EntityInfo getEntityInfo(PsiType type, List<MethodApiInfo.FieldInfo> sub, JSONObject json, RepeatCheck repeatCheck) {

        if (type instanceof PsiClassReferenceType) {
            PsiClassReferenceType types = (PsiClassReferenceType) type;
            PsiClass resolve = types.resolve();

            if (resolve == null || resolve.getQualifiedName() == null || resolve.getQualifiedName().startsWith("java.lang")) {
                return null;
            }
            MethodApiInfo.EntityInfo entityInfo = new MethodApiInfo.EntityInfo();
            entityInfo.entityClass = resolve.getQualifiedName();
            entityInfo.nameEn = resolve.getName();
            entityInfo.nameCn = TextParser.getEntityNote(resolve);
            entityInfo.fieldInfos = new ArrayList<>();
            List<PsiField> fields = new ArrayList<>();
            sub.add(entityInfo);
            // 获取所有字段
            getAllFields(fields, resolve);
            // 获取泛型
            Map<String, PsiType> genericType = getGenericType(types);

            // 遍历
            for (PsiField field : fields) {
                if (TextParser.hideField(field)
                        || excludeFields.contains(field.getName())) {
                    continue;
                }
                entityInfo.fieldInfos.add(getFieldInfo(entityInfo, field, genericType, sub, json, repeatCheck));
            }
            // 对泛型进行解析
            if (!genericType.isEmpty()) {
                StringBuilder generic = new StringBuilder("<");
                for (Map.Entry<String, PsiType> psiType : genericType.entrySet()) {
                    String nameEn = null;
                    if (psiType.getValue() instanceof PsiClassReferenceType entryTypes) {
                        PsiClass entryResolve = entryTypes.resolve();

                        if (entryResolve != null && entryResolve.getQualifiedName() == null && entryResolve.getQualifiedName().startsWith("java.lang")) {
                            nameEn = entryResolve.getName();
                        }
                    }
//                    MethodApiInfo.EntityInfo info = getEntityInfo(psiType.getValue(), sub, json, repeatCheck);
                    generic.append(nameEn != null ? nameEn : psiType.getKey()).append(", ");
                }
                entityInfo.nameEn = entityInfo.nameEn + generic.substring(0, generic.length() - 2) + ">";
            }
            return entityInfo;
        }
        return null;
    }

    public static void getPageInfo(PsiType type, List<MethodApiInfo.FieldInfo> sub, JSONObject json, RepeatCheck repeatCheck) {

        if (type instanceof PsiClassReferenceType) {

            PsiClassReferenceType types = (PsiClassReferenceType) type;
            PsiClass resolve = types.resolve();

            MethodApiInfo.EntityInfo entityInfo = new MethodApiInfo.EntityInfo();
            entityInfo.entityClass = resolve.getQualifiedName();
            entityInfo.nameEn = "IPage";
            entityInfo.nameCn = "分页信息";
            entityInfo.fieldInfos = new ArrayList<>();
            List<PsiField> fields = new ArrayList<>();
            // 获取所有字段
            getAllFields(fields, resolve);
            // 获取泛型
            Map<String, PsiType> genericType = getGenericType(types);
            // 遍历
            for (PsiMethod allMethod : resolve.getAllMethods()) {
                String trim = getTrim(allMethod.getName());
                PsiType returnType = allMethod.getReturnType();
                if (returnType != null && StringUtil.pageInfo.containsKey(trim)) {
                    MethodApiInfo.FieldInfo fieldInfo = new MethodApiInfo.FieldInfo();
                    fieldInfo.nameEn = trim;
                    fieldInfo.serial = entityInfo.subSerialCount++;
                    fieldInfo.information = StringUtil.pageInfo.get(trim);
                    fieldInfo.isNecessary = "N";
                    fieldInfo.type = getType(returnType, trim, getGenericType(types), sub, json, repeatCheck);
                    fieldInfo.nameCn = fieldInfo.information;
                    entityInfo.fieldInfos.add(fieldInfo);
                }
            }
            sub.add(entityInfo);
        }
    }

    public static String getTrim(String args) {
        if (StringUtil.isNotBlank(args) && args.startsWith("get")) {
            String get = args.replace("get", "");
            if (get.length() > 0) {
                return get.replaceFirst(get.substring(0, 1), get.substring(0, 1).toLowerCase(Locale.ROOT));
            } else {
                return get;
            }
        }
        return args;
    }

    public static void getAllFields(List<PsiField> fields, PsiClass resolve) {
        if (resolve == null) {
            return;
        }
        Set<PsiField> psiFields = Arrays.stream(resolve.getAllFields())
                // 非静态字段
                .filter(e -> !e.hasModifierProperty(PsiModifier.STATIC)
                        // 非瞬态字段
                        && !e.hasModifierProperty(PsiModifier.TRANSIENT)).collect(Collectors.toSet());
        fields.addAll(psiFields);
    }

    public static MethodApiInfo.FieldInfo getParameterInfo(PsiType type, PsiAnnotation annotation, String fieldName, JSONObject json, RepeatCheck repeatCheck) {
        MethodApiInfo.FieldInfo field = new MethodApiInfo.FieldInfo();
        field.nameCn = TextParser.getText(annotation, "name", "value");
        field.nameEn = fieldName;
        field.nameCn = StringUtil.isBlank(field.nameCn) ? field.nameEn : field.nameCn;
        field.type = getType(type, fieldName, new HashMap<>(), new ArrayList<>(), json, repeatCheck);
        field.isNecessary = Boolean.parseBoolean(TextParser.getText(annotation, false, "required")) ? "Y" : "N";
        field.defaultValue = TextParser.getValue(annotation, "defaultValue");
        // 有默认值则填入默认值
        if (StringUtil.isNotBlank(field.defaultValue)) {
            json.put(fieldName, field.defaultValue);
        }
        field.requestType = parseRequestType(annotation.getQualifiedName());
        return field;
    }

    public static String parseRequestType(String type) {
        if (PathVariable.equals(type)) {
            return "Path";
        } else if (RequestParam.equals(type)) {
            return "Param";
        } else if (RequestBody.equals(type)) {
            return "Body";
        } else if (RequestHeader.equals(type)) {
            return "Header";
        }
        return "";
    }

    public static MethodApiInfo.FieldInfo getFieldInfo(MethodApiInfo.EntityInfo entityInfo, PsiField field,
                                                       Map<String, PsiType> genericType,
                                                       List<MethodApiInfo.FieldInfo> sub, JSONObject json, RepeatCheck repeatCheck) {
        MethodApiInfo.FieldInfo fieldInfo = new MethodApiInfo.FieldInfo();
        PsiAnnotation annotation = getFieldAnn(field);
        fieldInfo.nameEn = field.getName();
        fieldInfo.serial = entityInfo.subSerialCount++;
        fieldInfo.information = getInformation(annotation);
        fieldInfo.isNecessary = Boolean.parseBoolean(TextParser.getText(annotation, "required")) ? "Y" : "N";
        fieldInfo.type = getType(field, genericType, sub, json, repeatCheck);
        fieldInfo.nameCn = getSubString(TextParser.getText(annotation, "value", "name", "title", "description"));
        fieldInfo.nameCn = StringUtil.isNotBlank(fieldInfo.nameCn) ? fieldInfo.nameCn : fieldInfo.nameEn;
        return fieldInfo;
    }

    public static PsiAnnotation getFieldAnn(PsiField field) {
        PsiAnnotation annotation = field.getAnnotation(ApiModelProperty);
        if (annotation != null) {
            return annotation;
        }
        return field.getAnnotation(Schema);
    }

    public static String getInformation(PsiAnnotation annotation) {
        String notes = TextParser.getText(annotation, "notes", "name", "title");
        if (notes != null && !notes.equals("")) {
            return notes;
        }
        notes = parseSymbol(TextParser.getText(annotation, "value"));
        if (notes == null || notes.equals("")) {
            return "";
        }
        if (notes.indexOf("(") > 0 && notes.indexOf(")") > 0) {
            return notes.substring(notes.indexOf("(") + 1, notes.indexOf(")"));
        }
        return "";
    }

    public static String parseSymbol(String s) {
        if (s != null) {
            return s.replaceAll("（", "(")
                    .replaceAll("）", ")")
                    .replaceAll("，", ",")
                    .replaceAll("≥", ">=")
                    .replaceAll("≤", "<=")
                    .replaceAll("！", "!")
                    .replaceAll("＜", "<");
        }
        return s;
    }

    public static String getSubString(String args) {
        if (StringUtil.isNotBlank(args)) {
            if (args.indexOf("(") > 0) {
                return args.substring(0, args.indexOf("("));
            }
            if (args.indexOf("（") > 0) {
                return args.substring(0, args.indexOf("（"));
            }
        }
        return args;
    }

    public static Map<String, PsiType> getGenericType(PsiClassReferenceType type) {
        PsiClassType.ClassResolveResult classResolveResult = type.resolveGenerics();
        PsiClass element = classResolveResult.getElement();
        element.hasTypeParameters();
        Map<String, PsiType> map = new HashMap<>();
        Map<PsiTypeParameter, PsiType> substitutionMap = classResolveResult.getSubstitutor().getSubstitutionMap();
        if (substitutionMap != null) {
            substitutionMap.forEach((k, v) -> {
                map.put(k.getName(), v);
            });
        }
        return map;
    }

    static String[] primitive = {"short", "byte", "int", "long", "boolean", "char", "float", "double"};
    static String[] primitives = {"数字整形", "数字整形", "数字整形", "数字整形", "布尔型", "字符型", "浮点型", "浮点型"};
    static Object[] primitiveValues = {0, 0, 0, 0, true, 'c', 0.1, 0.1};

    public static String getPrimitive(String fieldName, PsiType type, JSONObject jsonObject) {

        for (int i = 0; i < primitive.length; i++) {
            String name = ((PsiPrimitiveType) type).getName();
            if (primitive[i].equals(name)) {
                jsonObject.put(fieldName, primitiveValues[i]);
                return primitives[i];
            }
        }
        return null;
    }

    public static Object getPrimitiveVal(PsiType type) {

        for (int i = 0; i < primitive.length; i++) {
            String name = ((PsiPrimitiveType) type).getName();
            if (primitive[i].equals(name)) {
                return primitiveValues[i];
            }
        }
        return null;
    }


    public static String getType(PsiField field, Map<String, PsiType> genericType,
                                 List<MethodApiInfo.FieldInfo> sub, JSONObject jsonObject, RepeatCheck repeatCheck) {
        return getType(field.getType(), field.getName(), genericType, sub, jsonObject, repeatCheck);
    }

    public static String getType(PsiType types, String fieldName, Map<String, PsiType> genericType,
                                 List<MethodApiInfo.FieldInfo> sub, JSONObject jsonObject, RepeatCheck repeatCheck) {
        String name = fieldName;
        // 处理原始数据类型
        if (types instanceof PsiPrimitiveType) {
            return getPrimitive(name, types, jsonObject);
        }
        if (types instanceof PsiClassReferenceType) {
            PsiClassReferenceType type = (PsiClassReferenceType) types;

            // 处理泛型
            if (type.resolve() instanceof PsiTypeParameter) {
                PsiType psiType = genericType.get(type.resolve().getName());
                if (psiType == null || psiType instanceof PsiWildcardType) {
                    jsonObject.put(name, "object");
                    return "Object";
                }
                type = (PsiClassReferenceType) psiType;
            }
            // 处理通用对象
            if (isAssignable(type.resolve(), String.class.getName())) {
                jsonObject.put(name, "string");
                return "字符型";
            }
            if (isAssignable(type.resolve(), Boolean.class.getName())) {
                jsonObject.put(name, true);
                return "布尔型";
            }
            if (isAssignable(type.resolve(), BigDecimal.class.getName())) {
                jsonObject.put(name, 0.000001);
                return "数字类型";
            }
            if (isAssignable(type.resolve(), Integer.class.getName()) || isAssignable(type.resolve(), Long.class.getName())) {
                jsonObject.put(name, 1);
                return "数字整型";
            }
            if (isAssignable(type.resolve(), Double.class.getName()) || isAssignable(type.resolve(), Float.class.getName())) {
                jsonObject.put(name, 0.1);
                return "浮点型";
            }
            if (isAssignable(type.resolve(), Date.class.getName())) {
                jsonObject.put(name, "1997-01-01");
                return "日期型";
            }

            // 对象,json考虑循环引用
            jsonObject.put(name, dealWithClassGeneric(type, genericType, sub, repeatCheck));

            return replaceParameter(type.getPresentableText(), genericType);
        }
        jsonObject.put(name, dealWithGeneric(types, genericType, sub, repeatCheck));
        if (types instanceof PsiArrayType) {
            return "数组";
        }
        return "Object";
    }

    public static Object dealBasicType(PsiType types, Map<String, PsiType> genericType) {
        if (types instanceof PsiPrimitiveType) {
            return getPrimitiveVal(types);
        }
        PsiClassReferenceType type = (PsiClassReferenceType) types;

        // 处理泛型
        if (type.resolve() instanceof PsiTypeParameter) {
            PsiType psiType = genericType.get(type.resolve().getName());
            if (psiType == null || psiType instanceof PsiWildcardType) {
                return "object";
            }
            type = (PsiClassReferenceType) psiType;
        }
        // 处理通用对象
        if (isAssignable(type.resolve(), String.class.getName())) {
            return "string";
        }
        if (isAssignable(type.resolve(), Boolean.class.getName())) {
            return true;
        }
        if (isAssignable(type.resolve(), BigDecimal.class.getName())) {
            return "10000000.0";
        }
        if (isAssignable(type.resolve(), Integer.class.getName()) || isAssignable(type.resolve(), Long.class.getName())) {
            return 1;
        }
        if (isAssignable(type.resolve(), Double.class.getName()) || isAssignable(type.resolve(), Float.class.getName())) {
            return 0.1;
        }
        if (isAssignable(type.resolve(), Date.class.getName())) {
            return "1997-01-01";
        }
        return "object";
    }

    public static String replaceParameter(String s, Map<String, PsiType> genericType) {
        if (s.contains("<")) {
            Set<String> strings = splitAll(s);
            String pre = s.substring(0, s.indexOf("<"));
            String suf = s.substring(s.indexOf("<"));
            for (String string : strings) {
                if (genericType.containsKey(string)) {
                    String presentableText = genericType.get(string).getPresentableText();
                    if (presentableText != null) {
                        suf = suf.replace(string, presentableText);
                    }
                }
            }
            return pre + suf;
        }
        return s;
    }

    public static Set<String> splitAll(String args) {
        Set<String> set = new HashSet<>();
        Set<String> set1 = new HashSet<>();
        for (String s : args.split("<")) {
            set1.addAll(List.of(s.split(">")));
        }
        for (String s : set1) {
            set.addAll(List.of(s.split(",")));
        }
        return set.stream().map(String::trim).collect(Collectors.toSet());
    }

    public static boolean isAssignable(PsiClass psiClass, String args) {
        return isAssignable(new HashSet<>(), psiClass, args);
    }

    public static boolean isAssignable(Set<String> set, PsiClass psiClass, String args) {
        if (psiClass.getQualifiedName() != null && psiClass.getQualifiedName().equals(args)) {
            return true;
        }
        List<PsiClass> superClasses = new ArrayList<>();
        superClasses.addAll(List.of(psiClass.getInterfaces()));
        superClasses.addAll(List.of(psiClass.getSupers()));
        for (PsiClass aClass : superClasses) {
            if (!set.contains(aClass.getQualifiedName())) {
                if (isAssignable(set, aClass, args)) {
                    return true;
                }
                set.add(aClass.getQualifiedName());
            }
        }
        return false;
    }


    public static String getTypeSimpleName(Type actualType) {
        if (actualType instanceof ParameterizedType) {
            ParameterizedType p = (ParameterizedType) actualType;
            String typeName = p.getRawType().getTypeName();
            return typeName.substring(typeName.lastIndexOf(".") + 1);
        }
        return actualType.getTypeName();
    }

    public static boolean entityExists(List<MethodApiInfo.FieldInfo> sub, String exist) {
        for (MethodApiInfo.FieldInfo entityInfo : sub) {
            if (entityInfo instanceof MethodApiInfo.EntityInfo entity) {
                if (Objects.equals(exist, entity.entityClass)) {
                    return true;
                }
            }

        }
        return false;
    }

    public static Object dealWithGeneric(PsiType type, Map<String, PsiType> genericType, List<MethodApiInfo.FieldInfo> sub, RepeatCheck repeatCheck) {
        // 处理类
        if (type instanceof PsiClassReferenceType) {
            return dealWithClassGeneric((PsiClassReferenceType) type, genericType, sub, repeatCheck);
        }
        // 处理数组
        if (type instanceof PsiArrayType) {
            JSONArray array = new JSONArray();
            if (genericType == null) {
                return array;
            }

            // 处理泛型
            array.add(dealWithGeneric(((PsiArrayType) type).getComponentType(), genericType, sub, repeatCheck));

            return array;
        }
        // 处理基础数据对象
        if (type instanceof ParameterizedType) {
            return dealBasicType(type, genericType);
        }
        return "object";
    }

    public static Object dealWithClassGeneric(PsiClassReferenceType type, Map<String, PsiType> genericType, List<MethodApiInfo.FieldInfo> sub, RepeatCheck repeatCheck) {
        if (type == null) {
            return null;
        }
        // 循环检测
        RepeatCheck check = new RepeatCheck(type, repeatCheck);
        if (check.isCycle()) {
            return "...";
        }
//        todo 字段对象解析
        boolean isMap = isAssignable(type.resolve(), map);
        // 处理集合
        if (isAssignable(type.resolve(), collection)
                || isMap) {
            JSONArray array = new JSONArray();
            if (genericType == null) {
                return array;
            }
            // 合并泛型
            Map<String, PsiType> genericType1 = getGenericType(type);
            if (genericType1.size() > 0 && genericType.size() > 0) {
                for (Map.Entry<String, PsiType> entry : genericType1.entrySet()) {
                    String presentableText = entry.getValue().getPresentableText();
                    if (genericType.containsKey(presentableText)) {
                        entry.setValue(genericType.get(presentableText));
                    }
                }
            }
            // 处理泛型
            for (PsiType actualType : genericType1.values()) {
                Object o = dealWithGeneric(actualType, genericType, sub, check);
                array.add(o);
            }
            JSONObject mapObj = new JSONObject();
            mapObj.put("entry1", "{}");
            mapObj.put("entry2", "{}");
            mapObj.put("entry3", "{}");
            return isMap ? mapObj : array;
        }
        // 处理对象
        else {
            return getClassInfo(type, sub, check);
        }
    }

    public static Object getClassInfo(PsiClassReferenceType actualType,
                                      List<MethodApiInfo.FieldInfo> sub, RepeatCheck repeatCheck) {
        PsiClass resolve = actualType.resolve();
        if (resolve != null) {
            JSONObject json = new JSONObject();
            String name = resolve.getName();
            if (name != null && name.contains("IPage")) {
                System.out.println();
            }

            // 只解析有实体注解的对象
            if (entityAnn(resolve)
                    && !excludeClass.contains(resolve.getName())
                    && !entityExists(sub, resolve.getQualifiedName())) {
                getEntityInfo(actualType, sub, json, repeatCheck);
                return json;
            }

            Map<String, PsiType> genericType = getGenericType(actualType);
            // 如果字段里面有集合 继续迭代解析
            List<PsiField> fields = new ArrayList<>();
            getAllFields(fields, resolve);
            if (fieldContainsCollection(fields)) {
                for (PsiField field : fields) {
                    getType(field, genericType, sub, json, repeatCheck);
                }
                return json;
            }
            // 如果是泛型继续迭代
            if (name != null && name.contains("IPage")) {
                getPageInfo(actualType, sub, json, repeatCheck);
                return json;
            }
            // 处理基础类型
            return dealBasicType(actualType, genericType);
        }
        return null;
    }

    public static boolean entityAnn(PsiClass resolve ) {
        return resolve.getAnnotation(ApiModel) != null
                || resolve.getAnnotation(Schema) != null;
    }

    public static boolean fieldContainsCollection(List<PsiField> fields) {
        for (PsiField field : fields) {
            if (field.getType() instanceof PsiClassReferenceType) {
                PsiClassReferenceType referenceType = (PsiClassReferenceType) field.getType();
                PsiClass psiClass = referenceType.resolve();
                if (psiClass != null && isAssignable(psiClass, collection)) {
                    return true;
                }
            }
        }
        return false;
    }


    public static String getEntityDesc(PsiAnnotation api) {
        if (api == null) {
            return "";
        }

        String s;
        if (StringUtil.isNotBlank(s = getText(api, "value"))) {
            return s;
        }
        if (StringUtil.isNotBlank(s = getText(api, "description"))) {
            return s;
        }
        return "";
    }

    public static String getNote(PsiAnnotation api) {
        if (api == null) {
            return "";
        }
        PsiAnnotationMemberValue value = api.findAttributeValue("value");
        return value == null ? "" : match(value.getText());
    }

    public static String getText(PsiAnnotation api, String attribute) {
        if (api == null) {
            return null;
        }
        PsiAnnotationMemberValue value = api.findAttributeValue(attribute);
        return value == null ? "" : match(value.getText());
    }

    public static String match(String s) {
        Matcher matcher = p.matcher(s);
        if (matcher.find()) {
            return matcher.group();
        }
        return null;
    }

    public static String formatPath(String s) {
        if (s != null) {
            if (!s.startsWith("/")) {
                s = "/" + s;
            }
            if (s.endsWith("/")) {
                s = s.substring(0, s.length() - 1);
            }
            return s;
        }
        return s;
    }

}
